package com.changpei.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.changpei.common.cache.RedisUtil;
import com.changpei.common.cache.UserCache;
import com.changpei.common.result.Result;
import com.changpei.common.utils.FilePrefix;
import com.changpei.common.utils.JsonUtil;
import com.changpei.core.feign.UserFeign;
import com.changpei.core.pojo.User;
import com.changpei.search.dao.UserIndexMapper;
import com.changpei.search.pojo.UserIndex;
import com.changpei.search.service.UserIndexService;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * <p>Title: User</p>
 * <p>Description: User业务层接口实现类</p>
 * @author weibiao
 */
@Service
@Slf4j
@SuppressWarnings("all")
public class UserIndexServiceImpl implements UserIndexService {

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private UserIndexMapper userIndexMapper;

    @Autowired
    private UserCache userCache;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void importData() {
        String isValid = "http";
        long userPosition = userCache.getUserPosition();
        try {
            List<User> users = userFeign.findBaseId(userPosition).getData();
            List<UserIndex> collect = users.stream().map(user -> {
                UserIndex userIndex = JsonUtil.jsonToBean(user, UserIndex.class);
                if (!userIndex.getAvatarUrl().contains(isValid)) {
                    userIndex.setAvatarUrl(FilePrefix.AVATAR_URL_PREFIX + userIndex.getAvatarUrl());
                }
                return userIndex;
            }).collect(Collectors.toList());

            collect.forEach(user -> {
                userIndexMapper.save(user);
                userCache.setUserPosition();
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public Result<String> save(UserIndex userIndex) {
        try {
            userIndexMapper.save(userIndex);
            return Result.ok();
        } catch (Exception e) {
            log.warn("User数据新增ES库失败", e.getMessage());
            return Result.failed();
        }
    }

    @Override
    public Result<String> update(UserIndex userIndex) {
        try {
            userIndexMapper.save(userIndex);
            return Result.ok();
        } catch (Exception e) {
            log.warn("User数据更新ES库失败", e.getMessage());
            return Result.failed();
        }
    }

    @Override
    public Result<String> deleteById(Long id) {
        try {
            userIndexMapper.deleteById(id);
            return Result.ok();
        } catch (Exception e) {
            log.warn("删除User - ES库失败", e.getMessage());
            return Result.failed();
        }
    }

    @Override
    public UserIndex findById(Long id) {
        Optional<UserIndex> index = userIndexMapper.findById(id);
        if (ObjectUtils.isEmpty(index)) {
            return new UserIndex();
        }
        return index.get();
    }

    @Override
    public List<UserIndex> findAll() {
        return Lists.newArrayList(userIndexMapper.findAll());
    }

    @Override
    public Page<UserIndex> getFollowers(Long userId, int pageNum, int pageSize) {
        return userIndexMapper.search(userFollowQuery(pageNum, pageSize, userCache.followers(userId)));
    }

    @Override
    public Map<String, Object> getFans(Long userId, int pageNum, int pageSize) {

        Map<String, Object> map = new HashMap<>(2);

        // 我的粉丝
        Set<Long> fans = userCache.fans(userId);

        // 我的关注
        Set<Long> followers = userCache.followers(userId);

        // 构建查询条件
        NativeSearchQuery nativeSearchQuery = userFollowQuery(pageNum, pageSize, fans);

        Page<UserIndex> pageInfo = userIndexMapper.search(nativeSearchQuery);

        // 计算互相关注
        Set<Object> inter = new HashSet<>();

        if (!fans.isEmpty() && !followers.isEmpty()) {
            // 关注临时key
            String followersKey = UUID.randomUUID().toString();

            // 粉丝临时key
            String fansKey = UUID.randomUUID().toString();

            redisUtil.sSetWithTime(followersKey, 30, fans.toArray());
            redisUtil.sSetWithTime(fansKey, 30, followers.toArray());
            Set<Object> intersect = redisUtil.sIntersect(followersKey, fansKey);

            inter.addAll(intersect);
        }


        List<UserIndex> userIndices = pageInfo.getContent();
        List<JSONObject> objectList = new ArrayList<>();
        for (UserIndex userIndex : userIndices) {
            JSONObject obJson = JSONObject.parseObject(JSON.toJSONString(userIndex));
            obJson.put("eachAttention", false);
            for (Object o : inter) {
                if (userIndex.getId().equals(Long.parseLong(o.toString()))) {
                    obJson.put("eachAttention", true);
                }
            }
            objectList.add(obJson);
        }

        map.put("total", pageInfo.getTotalElements());
        map.put("content", objectList);

        return map;
    }

    @Override
    public Map<String, Object> getUserFollowers(Map<String, Object> map) {
        String token = map.get("token").toString();
        long userId = Long.parseLong(map.get("userId").toString());
        int pageNum = Integer.parseInt(map.get("pageNum").toString());
        int pageSize = Integer.parseInt(map.get("pageSize").toString());


        Map<String, Object> result = new HashMap<>(2);

        // 用户关注列表
        Set<Long> userFollowers = userCache.followers(userId);

        if (userFollowers.isEmpty()) {
            result.put("total", 0);
            result.put("content", new ArrayList<>());

            return result;
        }

        // 我的关注
        Set<Long> myFollowers = getMyFollowers(token);

        // 构建查询条件
        NativeSearchQuery nativeSearchQuery = userFollowQuery(pageNum, pageSize, userFollowers);

        Page<UserIndex> pageInfo = userIndexMapper.search(nativeSearchQuery);

        // 计算共同关注
        Set<Object> inter = new HashSet<>();

        if (!userFollowers.isEmpty() && !myFollowers.isEmpty()) {
            // 用户关注临时key
            String userFollowersKey = UUID.randomUUID().toString();

            // 我的关注临时key
            String myFollowKey = UUID.randomUUID().toString();

            redisUtil.sSetWithTime(userFollowersKey, 30, userFollowers.toArray());
            redisUtil.sSetWithTime(myFollowKey, 30, myFollowers.toArray());
            Set<Object> intersect = redisUtil.sIntersect(userFollowersKey, myFollowKey);

            inter.addAll(intersect);
        }

        List<UserIndex> userIndices = pageInfo.getContent();
        List<JSONObject> objectList = new ArrayList<>();
        for (UserIndex userIndex : userIndices) {
            JSONObject obJson = JSONObject.parseObject(JSON.toJSONString(userIndex));
            obJson.put("commonConcern", false);
            for (Object o : inter) {
                if (userIndex.getId().equals(Long.parseLong(o.toString()))) {
                    obJson.put("commonConcern", true);
                }
            }
            objectList.add(obJson);
        }

        result.put("total", pageInfo.getTotalElements());
        result.put("content", objectList);

        return result;
    }

    @Override
    public Map<String, Object> getUserFans(Map<String, Object> map) {
        String token = map.get("token").toString();
        long userId = Long.parseLong(map.get("userId").toString());
        int pageNum = Integer.parseInt(map.get("pageNum").toString());
        int pageSize = Integer.parseInt(map.get("pageSize").toString());


        Map<String, Object> result = new HashMap<>(2);

        // 用户粉丝列表
        Set<Long> userFans = userCache.fans(userId);

        if (userFans.isEmpty()) {
            result.put("total", 0);
            result.put("content", new ArrayList<>());

            return result;
        }

        // 我的关注
        Set<Long> myFollowers = getMyFollowers(token);

        // 构建查询条件
        NativeSearchQuery nativeSearchQuery = userFollowQuery(pageNum, pageSize, userFans);

        Page<UserIndex> pageInfo = userIndexMapper.search(nativeSearchQuery);

        List<UserIndex> userIndices = pageInfo.getContent();
        List<JSONObject> objectList = new ArrayList<>();
        for (UserIndex userIndex : userIndices) {
            JSONObject obJson = JSONObject.parseObject(JSON.toJSONString(userIndex));
            obJson.put("follow", false);
            for (Object o : myFollowers) {
                if (userIndex.getId().equals(Long.parseLong(o.toString()))) {
                    obJson.put("follow", true);
                }
            }
            objectList.add(obJson);
        }

        result.put("total", pageInfo.getTotalElements());
        result.put("content", objectList);

        return result;
    }

    @Override
    public Map<String, Object> userSearch(Map<String, Object> map) {

        Map<String, Object> result = new HashMap<>(2);

        String token = map.get("token").toString();
        String nickName = map.get("nickName").toString();
        int pageNum = Integer.parseInt(map.get("pageNum").toString());
        int pageSize = Integer.parseInt(map.get("pageSize").toString());

        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("nickName", nickName);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(fuzzyQueryBuilder);
        nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum - 1, pageSize));

        Page<UserIndex> indexPage = userIndexMapper.search(nativeSearchQueryBuilder.build());

        // 我的关注
        Set<Long> myFollowers = getMyFollowers(token);

        // 拼接是否关注
        List<JSONObject> objects = indexPage.getContent().stream().map(u -> {
            JSONObject o = JSONObject.parseObject(JSON.toJSONString(u));
            o.put("follow", false);
            myFollowers.forEach(followerId -> {
                if (u.getId().equals(Long.parseLong(followerId.toString()))) {
                    o.put("follow", true);
                }
            });
            return o;
        }).collect(Collectors.toList());

        result.put("total", indexPage.getTotalElements());
        result.put("content", objects);
        return result;
    }

    /**
     * 获取我的关注列表
     * @param token
     * @return
     */
    private Set<Long> getMyFollowers(String token) {
        return userCache.followers(token);
    }

    /**
     * 构建查询
     * @param pageNum
     * @param pageSize
     * @param set
     * @return
     */
    private NativeSearchQuery userFollowQuery(int pageNum, int pageSize, Set<Long> set) {
        TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("id", set);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(termsQuery);
        nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum - 1, pageSize));

        nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC));

        return nativeSearchQueryBuilder.build();
    }

}
